import math
from datetime import datetime

from backend.mydataset import FITDataset, GeoStyleDataset
from predict import PredictService

# 分组
keywords = {
    "category": ["clothing_category", "apparel"],
    "color": ["___product_color", "denim_wash_color", "major_color"],
    "outerwear": ["jacket", "outerwear"],
    "pattern": ["product_pattern", "clothing_pattern"],
    "sleeve_length": ["sleeve_length"],
    "neckline": ["neckline", "neckline_shape"],  # 领口
    "shoe_detail": ["shoe_closure"],
    "clothing_length": ["upper_body_length", "lower_body_length"],
    "toe_shape": ["toe_shape"],
    "collar": ["collar_presence"],  # 衣领
    "layers": ["multiple_layers"],
    "accessories": ["wearing_"],  # 附件（如帽子、眼镜、围巾）

    # ↓↓↓ 女性相关新增字段 ↓↓↓
    "bag_type": ["bag:"],
    "footwear_type": ["footwear:"],
    "heel_height": ["heel_height:"],
    "heel_type": ["heel_type:"],
    "sandal_type": ["sandal_type:"],
    "shoe_decoration": ["shoe_decoration:"],
    "dress_skirt_shape": ["dress_skirt_shape:"],
    "pants_fit_type": ["pants_fit_type:"],
    "rise_type": ["rise_type:"],
    "sleeve_style": ["sleeve_style:"],
    "shoe_type": ["shoe_type:"],  # ← 新增：鞋类细分类型（中性或正式鞋类）

    # 风格标签（非结构化，可直接在属性字符串中查找匹配）
    "style_tags": [
        "bohemian", "casual", "feminine", "minimalism", "modest",
        "sexy", "sophisticated", "sporty", "streetstyle", "fashion_statement",
        "business"  # ← 新增
    ],
}

predict_service = PredictService()


def categorize_attributes(attr_list, keyword_map):
    """
    根据关键词映射对属性进行分类

    参数:
    - attr_list: 待分类的属性列表
    - keyword_map: 字典，格式为 {"分类名": ["匹配词1", "匹配词2"]}

    返回:
    - 字典，包含分类结果和未匹配的"other"分类
    """
    result = {}
    other = []

    for attr in attr_list:
        attr_lower = attr.lower()
        matched = False

        # 检查属性是否匹配任一分类的任一关键词
        for category, keywords in keyword_map.items():
            for keyword in keywords:
                if keyword.lower() in attr_lower:
                    result.setdefault(category, []).append(attr)
                    matched = True
                    break  # 匹配到一个关键词就跳出当前分类循环
            if matched:
                break  # 已经匹配到分类，跳出外层循环

        # 如果没有任何分类匹配，放入other
        if not matched:
            other.append(attr)

    # 如果有未匹配的属性，添加到结果中
    if other:
        result['other'] = other

    return result


def filter_by_age_and_gender(attr_list, age, gender):
    genderM_skip_keywords = ['Dress', "apparel:upper_body_garment:dress",
                             "shoe_decoration:bow",
                             "clothing_pattern__Floral",
                             "clothing_pattern__Spotted",
                             "clothing_category__Tank top"
                             "Yes", "No"]

    female_skip_keywords = [
        "clothing_category__Suit",  # 正式西装，女性比例低或样式偏男性
        "wearing_necktie__Yes",  # 打领带：男女都可能有，但女性中极少见
        "clothing_category__Tank top",  # 同样出现在男性过滤中，女性中也偏少，尤其非夏季
        "apparel:upper_body_garment:shirt",  # shirt（中性偏男）、不如 blouse 更具女性风格
        "shoe_type:oxford_shoes",  # 牛津鞋是偏中性或偏男性鞋履
        "collar_presence__Yes",  # 带领服饰中包含衬衫、polo 等偏男性化设计
        "neckline:mandarin",  # 中山装立领，女性穿戴较少
        "neckline:henley",  # Henley 是男士无领开扣 Tee 样式
        "neckline:shawl",  # 披肩领较为特殊，数量极少
        "apparel:upper_body_garment:sweatshirt_hoodies"  # 过于休闲且中性，女性流行度低于毛衣、blouse,
        "Yes", "No"
    ]

    new_attr_list = []
    for attr in attr_list:
        if gender == "genderM" and any(keyword in attr for keyword in genderM_skip_keywords):
            continue
        if gender == "genderF" and any(keyword in attr for keyword in female_skip_keywords):
            continue

        if attr.startswith("FIT"):
            if age in attr and gender in attr:
                new_attr_list.append(attr)
        else:
            new_attr_list.append(attr)
    return new_attr_list


def select_max_trend_attribute(grouped_predictions):
    result = {}
    for group, attr_list in grouped_predictions.items():
        if not attr_list:
            continue
        # 找到value最大的项
        max_attr = max(attr_list, key=lambda x: x["value"])
        result[group] = max_attr
    return result


def cal_steps(attr, target_date):
    target_date = datetime.strptime(target_date, "%Y-%m-%d")
    if attr.startswith("FIT"):
        end_time = datetime.strptime(FITDataset.end_time, "%Y-%m-%d")
        delta = FITDataset.delta
    else:
        end_time = datetime.strptime(GeoStyleDataset.end_time, "%Y-%m-%d")
        delta = FITDataset.delta

    # 3. 计算时间差
    time_diff = (target_date - end_time).days

    # 4. 计算步长数（向上取整）
    steps = math.ceil(time_diff / delta)

    return steps


def recommend(city_name, age, gender, target_date, threshold=0.8):
    p = PredictService()
    attr_list = p.get_available_attributes(city_name)

    # 根据性别年龄过滤
    attr_list = filter_by_age_and_gender(attr_list, age, gender)

    groups = categorize_attributes(attr_list, keywords)
    # print(res)
    #
    # with open("temp/recommend.json", "w", encoding="utf-8") as f:
    #     json.dump(res, f, ensure_ascii=False, indent=4)

    selected_attributes = {}

    for group, attributes in groups.items():
        # 在每个组内，选择趋势值大于阈值的属性
        # 获取每个属性的预测值
        filtered_attributes = []
        for attr in attributes:
            steps = cal_steps(attr, target_date)
            value = predict_service.get_future_predict(city_name, attr, steps)[-1][1]
            if value > threshold:
                filtered_attributes.append({
                    "attr": attr,
                    "value": value,
                })

        if len(filtered_attributes):
            selected_attributes[group] = filtered_attributes

    # 返回每个组筛选后的属性
    v = select_max_trend_attribute(selected_attributes)
    res = []
    prompt = f"一张全身照片，一个时尚的年轻{'男' if gender == 'genderM' else '女'}性，身穿现代风格服饰，站立姿势，自然光照，背景简洁，画面高清，细节真实。关键词如下：\n"
    for group, d in v.items():
        prompt = prompt + f'{d["attr"].split("___", 3)[-1]}\n'
        res.append(d)

    return {
        "recommended_attributes": res,
        "prompt": prompt,
        "target_date": target_date,
        "city_info": {"city_name": city_name},
    }


if __name__ == "__main__":
    # v, prompt = recommend("Austin", "18-25", "genderM", 10)
    # v, prompt = recommend("Tokyo", "18-25", "genderF", 10)
    v, prompt = recommend("Beijing", "18-25", "genderM", '2020-08-01')

    print(v)

    print(prompt)
